use std::fmt::Display;

use super::{object::Object, text::SourceLocation, token::SyntaxToken};

#[derive(Debug)]
pub enum SyntaxResult {
    RuntimeError { token: SyntaxToken, message: String },
    ParserError { token: SyntaxToken, message: String },
    SystemError { message: String },
    Break,
    Return { value: Object },
}
impl SyntaxResult {
    pub fn ReturnValue(val:Object) -> SyntaxResult{
         SyntaxResult::Return { value: val }
    }
    pub fn RuntimeError(_token: &SyntaxToken, msg: &str) -> SyntaxResult {
        let err = SyntaxResult::RuntimeError {
            token: _token.clone(),
            message: msg.to_string(),
        };
        err.report();
        err
    }
    pub fn SystemError(msg: &str) -> SyntaxResult {
        let err = SyntaxResult::SystemError {
            message: msg.to_string(),
        };
        err.report();
        err
    }
    pub fn ParserError(_token: &SyntaxToken, msg: &str) -> SyntaxResult {
        let err = SyntaxResult::ParserError {
            token: _token.clone(),
            message: msg.to_string(),
        };
        err.report();
        err
    }

    pub fn report(&self) {
        eprintln!("{}", self);
    }
}

impl Display for SyntaxResult {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {

        match self {
            Self::RuntimeError { token, message } | 
            Self::ParserError  { token, message } => {
                write!(f, "SyntaxError: Token{}{{type:{:?}, str:'{}'}} msg:{}",token.local,token.kind,token.as_string(), message)
            },

            Self::SystemError { message } => write!(f, "SyntaxError: msg:{}", message),
            Self::Break => {write!(f, "")},
            Self::Return { value } => {write!(f, "")},
        }
    }
}
